#pragma once
#include "ShaderMap.h"
#include "MaterialParameter.h"

class Shader;
class ShaderType;
class VertexFactoryType;
class MaterialInstance;
struct ShaderDefineMap;

class Material
{
public:
	typedef void (*DefineType)(ShaderDefineMap* defineMap);
	enum EPass
	{
		EP_Base = 0,
		EP_DepthOnly,
		EP_Lighting,
		EP_Shadow,
		EP_Postprocess,
	};

public:
	Material(const std::string& name);
	~Material();

	inline const std::string& getName() const { return mName; }
	inline bool isTransparent() const { return mTransparent; }
	inline bool isMasked() const { return mMasked; }
	inline void setDefineType(DefineType define) { mDefine = define; }
	inline const MaterialParameter& getMaterialParam() const { return mMaterialParameter; }
	inline MaterialParameter& getMaterialParam() { return mMaterialParameter; }

	template<class ShaderType>
	ShaderType* getShader(const VertexFactoryType* vertexFactoryType) const
	{
		return (ShaderType*)getShader(&ShaderType::StaticType, vertexFactoryType);
	}
	Shader* getShader(const ShaderType* shaderType, const VertexFactoryType* vertexFactoryType) const
	{
		return mShaderMap.getShader(shaderType, vertexFactoryType);
	}

	void Define(ShaderDefineMap* defineMap);

	void BuildParamRef(const Shader* shader, MaterialParameterRefList& refList) const;

	void Compile();

	MaterialInstance* GetDefaultInstance() const { return mDefaultInstance; }
	MaterialInstance* CreateInstance() const;

private:
	const std::string mName;
	bool mTransparent;
	bool mMasked;

	MaterialInstance* mDefaultInstance;
	DefineType mDefine;
	MaterialShaderMap mShaderMap;
	MaterialParameter mMaterialParameter;
};